home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d927.lha / Telnet / src / ring.c < prev    next >
C/C++ Source or Header  |  1993-10-07  |  6KB  |  278 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)ring.c    5.1 (Berkeley) 9/14/90";
  22. #endif /* not lint */
  23.  
  24. /*
  25.  * This defines a structure for a ring buffer.
  26.  *
  27.  * The circular buffer has two parts:
  28.  *(((
  29.  *    full:    [consume, supply)
  30.  *    empty:    [supply, consume)
  31.  *]]]
  32.  *
  33.  */
  34.  
  35. #include    <stdio.h>
  36. #include    <errno.h>
  37.  
  38. #ifdef    size_t
  39. #undef    size_t
  40. #endif
  41.  
  42. #include    <sys/types.h>
  43. #ifndef    FILIO_H
  44. #include    <sys/ioctl.h>
  45. #endif
  46. #include    <sys/socket.h>
  47.  
  48. #include    "ring.h"
  49. #include    "general.h"
  50.  
  51. /* Internal macros */
  52.  
  53. #if    !defined(MIN)
  54. #define    MIN(a,b)    (((a)<(b))? (a):(b))
  55. #endif    /* !defined(MIN) */
  56.  
  57. #define    ring_subtract(d,a,b)    (((a)-(b) >= 0)? \
  58.                     (a)-(b): (((a)-(b))+(d)->size))
  59.  
  60. #define    ring_increment(d,a,c)    (((a)+(c) < (d)->top)? \
  61.                     (a)+(c) : (((a)+(c))-(d)->size))
  62.  
  63. #define    ring_decrement(d,a,c)    (((a)-(c) >= (d)->bottom)? \
  64.                     (a)-(c) : (((a)-(c))-(d)->size))
  65.  
  66.  
  67. /*
  68.  * The following is a clock, used to determine full, empty, etc.
  69.  *
  70.  * There is some trickiness here.  Since the ring buffers are initialized
  71.  * to ZERO on allocation, we need to make sure, when interpreting the
  72.  * clock, that when the times are EQUAL, then the buffer is FULL.
  73.  */
  74. static u_long ring_clock = 0;
  75.  
  76.  
  77. #define    ring_empty(d) (((d)->consume == (d)->supply) && \
  78.                 ((d)->consumetime >= (d)->supplytime))
  79. #define    ring_full(d) (((d)->supply == (d)->consume) && \
  80.                 ((d)->supplytime > (d)->consumetime))
  81.  
  82.  
  83.  
  84.  
  85.  
  86. /* Buffer state transition routines */
  87.  
  88. ring_init(ring, buffer, count)
  89. Ring *ring;
  90. char *buffer;
  91. int count;
  92. {
  93.     memset((char *)ring, 0, sizeof *ring);
  94.  
  95.     ring->size = count;
  96.  
  97.     ring->supply = ring->consume = ring->bottom = buffer;
  98.  
  99.     ring->top = ring->bottom+ring->size;
  100.  
  101.     return 1;
  102. }
  103.  
  104. /* Mark routines */
  105.  
  106. /*
  107.  * Mark the most recently supplied byte.
  108.  */
  109.  
  110. void
  111. ring_mark(ring)
  112. Ring *ring;
  113. {
  114.     ring->mark = ring_decrement(ring, ring->supply, 1);
  115. }
  116.  
  117. /*
  118.  * Is the ring pointing to the mark?
  119.  */
  120.  
  121. int
  122. ring_at_mark(ring)
  123. Ring *ring;
  124. {
  125.     if (ring->mark == ring->consume) {
  126.     return 1;
  127.     } else {
  128.     return 0;
  129.     }
  130. }
  131.  
  132. /*
  133.  * Clear any mark set on the ring.
  134.  */
  135.  
  136. void
  137. ring_clear_mark(ring)
  138. Ring *ring;
  139. {
  140.     ring->mark = 0;
  141. }
  142.  
  143. /*
  144.  * Add characters from current segment to ring buffer.
  145.  */
  146. void
  147. ring_supplied(ring, count)
  148. Ring *ring;
  149. int count;
  150. {
  151.     ring->supply = ring_increment(ring, ring->supply, count);
  152.     ring->supplytime = ++ring_clock;
  153. }
  154.  
  155. /*
  156.  * We have just consumed "c" bytes.
  157.  */
  158. void
  159. ring_consumed(ring, count)
  160. Ring *ring;
  161. int count;
  162. {
  163.     if (count == 0)    /* don't update anything */
  164.     return;
  165.  
  166.     if (ring->mark &&
  167.         (ring_subtract(ring, ring->mark, ring->consume) < count)) {
  168.     ring->mark = 0;
  169.     }
  170.     ring->consume = ring_increment(ring, ring->consume, count);
  171.     ring->consumetime = ++ring_clock;
  172.     /*
  173.      * Try to encourage "ring_empty_consecutive()" to be large.
  174.      */
  175.     if (ring_empty(ring)) {
  176.     ring->consume = ring->supply = ring->bottom;
  177.     }
  178. }
  179.  
  180.  
  181.  
  182. /* Buffer state query routines */
  183.  
  184.  
  185. /* Number of bytes that may be supplied */
  186. int
  187. ring_empty_count(ring)
  188. Ring *ring;
  189. {
  190.     if (ring_empty(ring)) {    /* if empty */
  191.         return ring->size;
  192.     } else {
  193.     return ring_subtract(ring, ring->consume, ring->supply);
  194.     }
  195. }
  196.  
  197. /* number of CONSECUTIVE bytes that may be supplied */
  198. int
  199. ring_empty_consecutive(ring)
  200. Ring *ring;
  201. {
  202.     if ((ring->consume < ring->supply) || ring_empty(ring)) {
  203.                 /*
  204.                  * if consume is "below" supply, or empty, then
  205.                  * return distance to the top
  206.                  */
  207.     return ring_subtract(ring, ring->top, ring->supply);
  208.     } else {
  209.                     /*
  210.                      * else, return what we may.
  211.                      */
  212.     return ring_subtract(ring, ring->consume, ring->supply);
  213.     }
  214. }
  215.  
  216. /* Return the number of bytes that are available for consuming
  217.  * (but don't give more than enough to get to cross over set mark)
  218.  */
  219.  
  220. int
  221. ring_full_count(ring)
  222. Ring *ring;
  223. {
  224.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  225.     if (ring_full(ring)) {
  226.         return ring->size;    /* nothing consumed, but full */
  227.     } else {
  228.         return ring_subtract(ring, ring->supply, ring->consume);
  229.     }
  230.     } else {
  231.     return ring_subtract(ring, ring->mark, ring->consume);
  232.     }
  233. }
  234.  
  235. /*
  236.  * Return the number of CONSECUTIVE bytes available for consuming.
  237.  * However, don't return more than enough to cross over set mark.
  238.  */
  239. int
  240. ring_full_consecutive(ring)
  241. Ring *ring;
  242. {
  243.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  244.     if ((ring->supply < ring->consume) || ring_full(ring)) {
  245.         return ring_subtract(ring, ring->top, ring->consume);
  246.     } else {
  247.         return ring_subtract(ring, ring->supply, ring->consume);
  248.     }
  249.     } else {
  250.     if (ring->mark < ring->consume) {
  251.         return ring_subtract(ring, ring->top, ring->consume);
  252.     } else {    /* Else, distance to mark */
  253.         return ring_subtract(ring, ring->mark, ring->consume);
  254.     }
  255.     }
  256. }
  257.  
  258. /*
  259.  * Move data into the "supply" portion of of the ring buffer.
  260.  */
  261. void
  262. ring_supply_data(ring, buffer, count)
  263. Ring *ring;
  264. char *buffer;
  265. int count;
  266. {
  267.     int i;
  268.  
  269.     while (count) {
  270.     i = MIN(count, ring_empty_consecutive(ring));
  271.     memcpy(ring->supply, buffer, i);
  272.     ring_supplied(ring, i);
  273.     count -= i;
  274.     buffer += i;
  275.     }
  276. }
  277.  
  278.